package cn.com.cifi.mars.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.com.cifi.mars.bean.bo.DictionaryCodeBO;
import cn.com.cifi.mars.bean.bo.SysLogBO;
import cn.com.cifi.mars.bean.bo.approval.ApprovalSubmitBO;
import cn.com.cifi.mars.bean.bo.projecyByStages.FullPathOrgData;
import cn.com.cifi.mars.bean.dto.ProjectByStagesDto;
import cn.com.cifi.mars.bean.vo.price.FilePreviewVO;
import cn.com.cifi.mars.bean.vo.returnPlan.ProjectReturnCoefficientVo;
import cn.com.cifi.mars.bean.vo.returnPlan.ReturnCoefficientContentVo;
import cn.com.cifi.mars.bean.vo.sys.rsp.GroupUserVo;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.BigStandardFormatsEnum;
import cn.com.cifi.mars.constant.CodeEnum;
import cn.com.cifi.mars.constant.Constants;
import cn.com.cifi.mars.constant.FetchNnumberEnum;
import cn.com.cifi.mars.constant.HrOrgTypeEunm;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.IsSuccessEnum;
import cn.com.cifi.mars.constant.LogEventEnum;
import cn.com.cifi.mars.constant.LogSrcEnum;
import cn.com.cifi.mars.constant.LogTypeEnum;
import cn.com.cifi.mars.constant.ProcessTypeEnum;
import cn.com.cifi.mars.constant.ReturnVersionTypeEnum;
import cn.com.cifi.mars.constant.SalyTypeEnum;
import cn.com.cifi.mars.constant.StandardFormatsEnum;
import cn.com.cifi.mars.constant.StandardFormatsMapEnum;
import cn.com.cifi.mars.constant.VersionCreateEnum;
import cn.com.cifi.mars.constant.VersionStatusEnum;
import cn.com.cifi.mars.entity.ApprovalBill;
import cn.com.cifi.mars.entity.ApprovalBillDetail;
import cn.com.cifi.mars.entity.ApprovalPreview;
import cn.com.cifi.mars.entity.ContentDetil;
import cn.com.cifi.mars.entity.DmCityReturnCoefficient;
import cn.com.cifi.mars.entity.InvestmentCoefficientJson;
import cn.com.cifi.mars.entity.InvestmentOfficialVersion;
import cn.com.cifi.mars.entity.MdmProject;
import cn.com.cifi.mars.entity.MdmProjectPatner;
import cn.com.cifi.mars.entity.PanoplanBuildPlanItem;
import cn.com.cifi.mars.entity.ProjectReturnCoefficient;
import cn.com.cifi.mars.entity.ReturnCoefficientContent;
import cn.com.cifi.mars.entity.ReturnCoefficientDetail;
import cn.com.cifi.mars.entity.common.IdmUser;
import cn.com.cifi.mars.mapper.mars.ApprovalPreviewMapper;
import cn.com.cifi.mars.mapper.mars.ProjectByStagesMapper;
import cn.com.cifi.mars.mapper.mars.ProjectMapper;
import cn.com.cifi.mars.mapper.mars.ProjectReturnCoefficientMapper;
import cn.com.cifi.mars.mapper.mars.ReturnCoefficientDetailMapper;
import cn.com.cifi.mars.mapper.wrapper.ProjectReturnCoefficientWrapper;
import cn.com.cifi.mars.mapper.wrapper.ReturnCoefficientDetailWrapper;
import cn.com.cifi.mars.service.ApprovalBillService;
import cn.com.cifi.mars.service.ApprovalPreviewService;
import cn.com.cifi.mars.service.FileUploadService;
import cn.com.cifi.mars.service.IdmUserService;
import cn.com.cifi.mars.service.ProjectBasicService;
import cn.com.cifi.mars.service.ProjectByStagesService;
import cn.com.cifi.mars.service.ProjectReturnCoefficientService;
import cn.com.cifi.mars.service.ProjectService;
import cn.com.cifi.mars.service.ReturnCoefficientDetailService;
import cn.com.cifi.mars.service.SignPlanVersionService;
import cn.com.cifi.mars.service.SubmitApprovedProjectService;
import cn.com.cifi.mars.service.SysLogService;
import cn.com.cifi.mars.util.BasicAuthClient;
import cn.com.cifi.mars.util.DateUtils;
import cn.com.cifi.mars.util.LocalDateTimeUtils;
import cn.com.cifi.mars.util.UUIDUtils;
import cn.com.cifi.mars.util.VersionUtils;
import cn.com.cifi.mars.util.WebUtils;
import cn.com.cifi.mars.util.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONSerializer;


/**
 * <p>
 * 项目回款系数表 服务实现类
 * </p>
 *
 * @author JingYuanXiang
 * @since 2020-11-05
 */
@Slf4j
@Service
public class ProjectReturnCoefficientServiceImpl extends ServiceImpl<ProjectReturnCoefficientMapper, ProjectReturnCoefficient> implements ProjectReturnCoefficientService {
    @Autowired
    private ProjectReturnCoefficientMapper returnCoefficientMapper;
    @Autowired
    private ReturnCoefficientDetailService returnCoefficientDetailService;
    @Autowired
    private ProjectReturnCoefficientWrapper projectReturnCoefficientWrapper;
    @Autowired
    private ReturnCoefficientDetailMapper returnCoefficientDetailMapper;
    @Autowired
    private IdmUserService idmUserService;
    @Autowired
    private ReturnCoefficientDetailWrapper returnCoefficientDetailWrapper;
    @Autowired
    private ApprovalPreviewService approvalPreviewService;
    @Autowired
    private ProjectBasicService projectBasicService;
    @Autowired
    private ProjectByStagesMapper projectByStagesMapper;
    @Autowired
    private ApprovalBillService approvalBillService;
    @Autowired
    private SubmitApprovedProjectService submitApprovedProjectService;
    @Autowired
    private SysLogService sysLogService;
    @Autowired
    private SignPlanVersionService signPlanVersionService;
    @Autowired
    private SysDictionaryServiceImpl sysDictionaryService;
    @Autowired
    private ApprovalPreviewMapper approvalPreviewMapper;
    @Autowired
    private FileUploadService fileUploadService;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ProjectByStagesService projectByStagesService;
    
    @Value("${api_name}")
    private String api_name;
    @Value("${api_key}")
    private String api_key;

    @Value("${coeffient_push_url}")
    private String investment_push_url;
    /**
     * 获取回款系数版本列表
     *
     * @param projectId 项目id
     * @param type      版本类型
     */
    @Override
    public List<ProjectReturnCoefficientVo> queryVersions(String projectId, String type) {
        List<ProjectReturnCoefficientVo> resultList = new ArrayList<>();
        List<ProjectReturnCoefficient> list = projectReturnCoefficientWrapper.selectCountByProjectIdAndVersionType(projectId, type, IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        } else {
            if (ReturnVersionTypeEnum.ADJUSTMENT.getKey().equals(type)) {
                for (ProjectReturnCoefficient projectReturnCoefficient : list) {
                    ProjectReturnCoefficientVo projectReturnCoefficientVo = new ProjectReturnCoefficientVo();
                    String userId = projectReturnCoefficient.getCreateBy();
                    IdmUser user = idmUserService.getById(userId);
                    String creatUser = user.getUsercn();
                    projectReturnCoefficientVo.setProjectReturnCoefficient(projectReturnCoefficient);
                    projectReturnCoefficientVo.setCreateUser(creatUser);
                    resultList.add(projectReturnCoefficientVo);
                }
            } else {
                for (ProjectReturnCoefficient projectReturnCoefficient : list) {
                    ProjectReturnCoefficientVo projectReturnCoefficientVo = new ProjectReturnCoefficientVo();
                    projectReturnCoefficientVo.setProjectReturnCoefficient(projectReturnCoefficient);
                    projectReturnCoefficientVo.setCreateUser("系统创建");
                    resultList.add(projectReturnCoefficientVo);
                }
            }
        }
        return resultList;
    }

    /**
     * 判断能否新建调整板回款系数
     * 新建版本
     *
     * @param projectId 项目id
     * @param user      用户信息
     */
    @Transactional
    @Override
    public ProjectReturnCoefficient create(String projectId, IdmUser user) {
        //参数校验
        if (StringUtils.isBlank(projectId) || null == user) {
            throw new MsgException(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }

        /*//获取区域财务人员(预算专员)的用户id（username）
        List<String> financeList = getFinancePm(projectId);
        if (CollectionUtils.isEmpty(financeList)) {
          throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_VERSION_ERROR);
        }
        //校验用户是否拥有权限
        //区域财务人员(预算专员)可以发起回款系数的调整，不允许其他人员发起;
        String username = user.getUsername();
        if (!financeList.contains(username)) {
          throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_NOT_AUTHORIZED_ERROR);
        }*/
        //查询分期数据
        ProjectByStagesDto project = projectByStagesMapper.selectByOrgdepid(projectId);
        if (null == project) {
            throw new MsgException(CodeEnum.SYS_PROJECT_ERROR);
        }
        //获取最新调整板版本状态
        ProjectReturnCoefficient coefficient = returnCoefficientMapper.getVersionStatus(projectId, IsDeleteEnum.NO.getKey());
        String versionNum = null;
        //如果调整版为空新建版本
        if (coefficient == null) {
            versionNum = "V1";
            //判断最新调整板版本状态是否为审批通过
        } else if ((coefficient.getVersionState()).equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())) {
            versionNum = VersionUtils.bigVersionInc(coefficient.getVersionNum());
        } else {
            throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_VERSION_STATUS_ERROR);
        }
        //根据项目id获取城市id
        String cityId = returnCoefficientDetailMapper.selectCityOfProject(projectId);

        ProjectReturnCoefficient projectReturnCoefficient = new ProjectReturnCoefficient();
        
        String coefficientId = UUIDUtils.create();
        projectReturnCoefficient.setId(coefficientId);
        projectReturnCoefficient.setProjectId(projectId);
        projectReturnCoefficient.setCityId(cityId);
        projectReturnCoefficient.setSyncTime(LocalDateTime.now());
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM");
        projectReturnCoefficient.setAffiliationMonth(df.format(LocalDateTime.now()));
        projectReturnCoefficient.setVersionType(ReturnVersionTypeEnum.ADJUSTMENT.getKey());
        projectReturnCoefficient.setVersionState(VersionStatusEnum.NOTPREPARED.getKey());
        projectReturnCoefficient.setVersionNum(versionNum);
        projectReturnCoefficient.setCreateBy(user.getUsername());
        projectReturnCoefficient.setCreateTime(LocalDateTime.now());
        projectReturnCoefficient.setCreateBy(user.getUsername());
        projectReturnCoefficient.setCreateTime(LocalDateTime.now());
        projectReturnCoefficient.setIsDelete(IsDeleteEnum.NO.getKey());
        projectReturnCoefficient.setDescription("创建调整版回款系数");
        projectReturnCoefficient.setVersionCreate(VersionCreateEnum.MANUALCREATE.getKey());
        //保存新建回款系数版本信息
        this.save(projectReturnCoefficient);

        //新建版本详情表
        returnCoefficientDetailService.saveDetail(coefficientId, user, projectId);

        return projectReturnCoefficient;
    }

    /**
     * 新建实际版回款系数
     * 新建版本
     *
     * @param projectId 项目id
     */
    @Override
    public ProjectReturnCoefficient createReality(String projectId) {
        //参数校验
        if (StringUtils.isBlank(projectId)) {
            throw new MsgException(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        //查询分期数据
        ProjectByStagesDto project = projectByStagesMapper.selectByOrgdepid(projectId);
        if (null == project) {
            throw new MsgException(CodeEnum.SYS_PROJECT_ERROR);
        }
        //获取全部实际版版本
        List<ProjectReturnCoefficient> coefficientList = returnCoefficientMapper.selectVersions(projectId, IsDeleteEnum.NO.getKey(), ReturnVersionTypeEnum.PRACTICAL.getKey());
        //根据项目id获取城市id
        String cityId = returnCoefficientDetailMapper.selectCityOfProject(projectId); //获取最新实际版版本状态
        //获取最新实际版
        ProjectReturnCoefficient coefficient = projectReturnCoefficientWrapper.selectNewestByProjectId(projectId, ReturnVersionTypeEnum.PRACTICAL.getKey(), IsDeleteEnum.NO.getKey());
        String versionNum = null;
        //如果实际版为空新建版本
        if (CollectionUtils.isEmpty(coefficientList)) {
            versionNum = "V1";
        } else {
            //判断月份
            LocalDateTime createTime = coefficient.getCreateTime();
            Month month = createTime.getMonth();
            if (month.equals(LocalDateTime.now().getMonth())){
                versionNum = coefficient.getVersionNum();
                if (StringUtils.isEmpty(versionNum)) {
                    versionNum = "V1";
                } else {
                    String s = versionNum.substring(1);
                    int i = Integer.parseInt(s);
                    versionNum = "V" + (++i);
                }
            }else {
                versionNum = "V1";
            }
        }
        ProjectReturnCoefficient projectReturnCoefficient = new ProjectReturnCoefficient();
        String coefficientId = UUIDUtils.create();//新建回款系数版本表id
        //判断coefficient是否为空
        if (null == coefficient) {
            //新增回款系数版本id
            projectReturnCoefficient.setId(coefficientId);
            //新增项目id
            projectReturnCoefficient.setProjectId(projectId);
            //城市id
            projectReturnCoefficient.setCityId(cityId);
            //设置为明源系统
            projectReturnCoefficient.setDataSource(FetchNnumberEnum.MY.getKey());
            //同步时间为现在
            projectReturnCoefficient.setSyncTime(LocalDateTime.now());
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM");
            //版本归属时间
            projectReturnCoefficient.setAffiliationMonth(df.format(LocalDateTime.now()));
            //版本类型为实际版
            projectReturnCoefficient.setVersionType(ReturnVersionTypeEnum.PRACTICAL.getKey());
            //版本状态系统生成
            projectReturnCoefficient.setVersionState(VersionStatusEnum.SYSGENERATION.getKey());
            projectReturnCoefficient.setVersionNum(versionNum);
            projectReturnCoefficient.setCreateBy(Constants.SYS);
            projectReturnCoefficient.setCreateTime(LocalDateTime.now());
            projectReturnCoefficient.setIsDelete(IsDeleteEnum.NO.getKey());
            projectReturnCoefficient.setVersionCreate(VersionCreateEnum.MANUALCREATE.getKey());
            //保存新建回款系数版本信息
            this.save(projectReturnCoefficient);
        } else {
            //创建调整板回款系数
            projectReturnCoefficient.setId(coefficientId);
            projectReturnCoefficient.setProjectId(projectId);
            projectReturnCoefficient.setCityId(coefficient.getCityId());
            projectReturnCoefficient.setDataSource(coefficient.getDataSource());
            projectReturnCoefficient.setSyncTime(LocalDateTime.now());
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM");
            projectReturnCoefficient.setAffiliationMonth(df.format(LocalDateTime.now()));
            projectReturnCoefficient.setVersionType(ReturnVersionTypeEnum.PRACTICAL.getKey());
            projectReturnCoefficient.setVersionState(VersionStatusEnum.SYSGENERATION.getKey());//版本状态为系统生成
            projectReturnCoefficient.setVersionNum(versionNum);
            projectReturnCoefficient.setCreateBy(Constants.SYS);
            projectReturnCoefficient.setCreateTime(LocalDateTime.now());
            projectReturnCoefficient.setIsDelete(IsDeleteEnum.NO.getKey());
            projectReturnCoefficient.setDescription(coefficient.getDescription());
            projectReturnCoefficient.setVersionCreate(VersionCreateEnum.MANUALCREATE.getKey());
            //保存新建回款系数版本信息
            this.save(projectReturnCoefficient);
        }
        return projectReturnCoefficient;
    }

    /**
     * 编辑调整板回款系数保存
     *
     * @param detailList 传入参数
     * @param user       用户
     */

    @Override
    public void createSupplyBudgetVersion(List<ReturnCoefficientDetail> detailList, IdmUser user) {
        if (CollectionUtils.isEmpty(detailList)) {
            throw new MsgException(CodeEnum.ILLEGAL_REQUEST_PARAM_ERROR);
        }
        //获取回款系数版本id
        String coefficientId = detailList.get(0).getCoefficientId();

        //获取版本
        ProjectReturnCoefficient returnCoefficient = returnCoefficientMapper.queryById(coefficientId);
        if (null==returnCoefficient){
            throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_VERSION_NOT_VERSION);

        }
        if (returnCoefficient.getVersionState().equals(VersionStatusEnum.APPROVED.getKey()) || returnCoefficient.getVersionState().equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())) {
            throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_VERSION);
        }

        //获取回款系数详情
        List<ReturnCoefficientDetail> list = returnCoefficientDetailWrapper.selectByCoefficientId(coefficientId, IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isEmpty(list)) {
            throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_ADJUSTMENT_VERSION_ERROR);
        }

        for (ReturnCoefficientDetail returnCoefficientDetail : list) {
            //获取回款系数详情表的产品构成父级编码
            String proProductCode = returnCoefficientDetail.getProProductCode();
            //param中的ProProductCode与详情表的ProProductCode相等时重新赋值并修改更新时间和更新人员
            //重新赋值
            for (ReturnCoefficientDetail detail : detailList) {
                if (detail.getProProductCode().equals(proProductCode)) {
                    returnCoefficientDetail.setOneMonth(detail.getOneMonth());
                    returnCoefficientDetail.setTwoMonth(detail.getTwoMonth());
                    returnCoefficientDetail.setThreeMonth(detail.getThreeMonth());
                    returnCoefficientDetail.setFourMonth(detail.getFourMonth());
                    returnCoefficientDetail.setFiveMonth(detail.getFiveMonth());
                    returnCoefficientDetail.setSixMonth(detail.getSixMonth());
                    returnCoefficientDetail.setSevenMonth(detail.getSevenMonth());
                    returnCoefficientDetail.setEightMonth(detail.getEightMonth());
                    returnCoefficientDetail.setNineMonth(detail.getNineMonth());
                    returnCoefficientDetail.setTenMonth(detail.getTenMonth());
                    returnCoefficientDetail.setElevenMonth(detail.getElevenMonth());
                    returnCoefficientDetail.setTwelveMonth(detail.getTwelveMonth());
                    returnCoefficientDetail.setThirteenMonth(detail.getThirteenMonth());
                    returnCoefficientDetail.setFourteenMonth(detail.getFourteenMonth());
                    returnCoefficientDetail.setFifteenMonth(detail.getFifteenMonth());
                    returnCoefficientDetail.setSixteenMonth(detail.getSixteenMonth());
                    returnCoefficientDetail.setSeventeenMonth(detail.getSeventeenMonth());
                    returnCoefficientDetail.setEighteenMonth(detail.getEighteenMonth());
                    returnCoefficientDetail.setNineteenMonth(detail.getNineteenMonth());
                    returnCoefficientDetail.setTwentyMonth(detail.getTwentyMonth());
                    returnCoefficientDetail.setTwentyOneMonth(detail.getTwentyOneMonth());
                    returnCoefficientDetail.setTwentyTwoMonth(detail.getTwentyTwoMonth());
                    returnCoefficientDetail.setTwentyThreeMonth(detail.getTwentyThreeMonth());
                    returnCoefficientDetail.setTwentyFourMonth(detail.getTwentyFourMonth());
                    returnCoefficientDetail.setUpdateTime(LocalDateTime.now());
                    returnCoefficientDetail.setUpdateBy(user.getUsername());
                    //保存回款系数详情表
                    returnCoefficientMapper.updateCoefficientDetail(proProductCode, coefficientId, returnCoefficientDetail);
                }
            }
        }
        String versionState = returnCoefficient.getVersionState();
        String versionStateAfter = "";
        //版本状态如果是待编制则改成编制中
        if (versionState.equals(VersionStatusEnum.NOTPREPARED.getKey())) {
        	versionStateAfter = VersionStatusEnum.ORGANIZATION.getKey();
        }
        returnCoefficientMapper.updateVersionState(coefficientId,user.getUsername(),versionStateAfter);
        //获取项目id
        String projectId = returnCoefficient.getProjectId();
        //待提交审批、审批已驳回状态的版本保存后更新审批快照表
        List<String> versionStatuss = Arrays.asList(VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.FAILUREAPPROVED.getKey());
        if (versionStatuss.contains(returnCoefficient.getVersionState())) {
            //获取在途审批单
            ApprovalBill approvalBill = approvalBillService.getNotSubmitApprovalBill(projectId, ProcessTypeEnum.MONEY_BACK_COEFFICIENT.getKey());
            //审批单id
            String examineId = approvalBill.getId();
            String contentString = getApprovalPreview(projectId, coefficientId, user, examineId);
            ReturnCoefficientContent content = JsonUtils.convertJsonToBean(contentString, ReturnCoefficientContent.class);
            //审批数据详情
            ReturnCoefficientContent newContent = getContent(projectId, coefficientId);
            if (content != null) {
                content.setVsCityMap(newContent.getVsCityMap());
                content.setVsInvestMap(newContent.getVsInvestMap());
                content.setVsRealityMap(newContent.getVsRealityMap());
            } else {
                content = newContent;
            }
            String countString = JSONObject.toJSONString(content);
            //更新审批快照表
            approvalPreviewService.saveData(examineId, countString, user);
        }
    }

    /**
     * 删除版本
     *
     * @param versionId 版本id
     */
    @Override
    public void delete(String versionId,IdmUser user) {
        //获取回款系数版本
        ProjectReturnCoefficient coefficient = projectReturnCoefficientWrapper.selectById(versionId, IsDeleteEnum.NO.getKey());
        if (coefficient == null) {
            throw new MsgException(CodeEnum.NON_VERSIONS);
        }
        //获取版本状态
        String versionState = coefficient.getVersionState();
        //调整版回款系数版本状态为【待编制】【编制中】可删除版本
        if (versionState.equals(VersionStatusEnum.NOTPREPARED.getKey()) || versionState.equals(VersionStatusEnum.ORGANIZATION.getKey())) {
            returnCoefficientMapper.delByVersionId(versionId,user.getUsername(),IsDeleteEnum.YES.getKey());
            returnCoefficientDetailWrapper.update(versionId,user.getUsername(),IsDeleteEnum.YES.getKey());
        } else {
            throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_VERSION_NOT_ALLOW_DELETE_ERROR);
        }
    }

    /**
     * 查询回款系数审批内容
     *
     * @param projectId     项目id
     * @param coefficientId 版本id
     * @return
     */
    @Override
    public String getApprovalPreview(String projectId, String coefficientId, IdmUser user, String examineId) {
        //查询是否存在未完成的审批单
        if (StringUtils.isBlank(examineId)) {
            ApprovalBill approvalBill = approvalBillService.getNotSubmitApprovalBill(projectId, ProcessTypeEnum.MONEY_BACK_COEFFICIENT.getKey());
            if (null != approvalBill) {
                examineId = approvalBill.getId();
            }
        }

        //1、若存在审批单,取审批预览表内容
        if (StringUtils.isNotBlank(examineId)) {
            String contentString = approvalPreviewService.getContentByApprovalId(examineId);
            ReturnCoefficientContent content = JsonUtils.convertJsonToBean(contentString, ReturnCoefficientContent.class);
            return JSONObject.toJSONString(content);
        }

        //参数校验
        if (StringUtils.isEmpty(projectId) && StringUtils.isEmpty(coefficientId)) {
            throw new MsgException(CodeEnum.REQUEST_PARAM_NOT_FULL_ERROR);
        }
        //2、若不存在审批单,计算生成审批预览内容
        ReturnCoefficientContent content = getContent(projectId, coefficientId);
        //content转成json字符串,再转成字符串
        return JSONObject.toJSONString(content);
    }

    /**
     * 获取审批内容
     *
     * @param projectId     项目id
     * @param coefficientId 版本id
     * @return
     */
    private ReturnCoefficientContent getContent(String projectId, String coefficientId) {
        //审批内容
        ReturnCoefficientContent content = new ReturnCoefficientContent();
        //权益比例
        content.setEquityRatio(getEquityRatioRate(projectId));
        //获取项目数据
        MdmProject mdmProject = projectMapper.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
        FullPathOrgData fullPathOrgData = projectByStagesService.getParentFullPathOrgData(projectId);
        //项目名称
        content.setProjectName(mdmProject.getProjectName());
        //项目区域
        content.setProjectArea(fullPathOrgData.getRegionName());
        //项目code
        content.setProjectCode(mdmProject.getProjectCode());
        //项目id
        content.setProjectId(projectId);
        //版本id
        content.setCoefficientId(coefficientId);
        //获取调整板版本信息
        ProjectReturnCoefficient coefficient = projectReturnCoefficientWrapper.selectById(coefficientId, IsDeleteEnum.NO.getKey());
        //本次调整板回款系数详情
        List<ReturnCoefficientDetail> adjustmentDetailList = returnCoefficientDetailWrapper.selectByCoefficientId(coefficientId, IsDeleteEnum.NO.getKey());

        //获取最新投资正式版版本
        ProjectReturnCoefficient returnCoefficient = projectReturnCoefficientWrapper.selectNewestByProjectId(projectId, ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey(), IsDeleteEnum.NO.getKey());
        if (null != returnCoefficient) {
            String id = returnCoefficient.getId();
            //最新投资正式版详情数据
            List<ReturnCoefficientDetail> investDetailList = returnCoefficientDetailWrapper.selectByCoefficientId(id, IsDeleteEnum.NO.getKey());
            Map<String, Map<String, ContentDetil>> vsInvestMap = getVsVersionList(adjustmentDetailList, investDetailList);
            content.setVsInvestMap(vsInvestMap);
        }

        //获取最新实际版版本
        ProjectReturnCoefficient practicalCoefficient = projectReturnCoefficientWrapper.selectNewestByProjectId(projectId, ReturnVersionTypeEnum.PRACTICAL.getKey(), IsDeleteEnum.NO.getKey());
        if (null != practicalCoefficient) {
            String practicalId = practicalCoefficient.getId();
            //实际版详情数据
            List<ReturnCoefficientDetail> practicalDetailList = returnCoefficientDetailWrapper.selectNewestByCoefficientId(practicalId, IsDeleteEnum.NO.getKey());
            Map<String, Map<String, ContentDetil>> vsPracticalList = getVsVersionList(adjustmentDetailList, practicalDetailList);
            content.setVsRealityMap(vsPracticalList);
        }

        //根据项目id获取城市id
        String cityId = returnCoefficientDetailMapper.selectCityOfProject(projectId);
        //获取回款系数版本更新时间
        LocalDateTime updateTime = coefficient.getUpdateTime();
        //减去一个月
        updateTime= updateTime.minusMonths(1);
        int year = updateTime.getYear();
        int monthValue = updateTime.getMonthValue();
        String yearMonth = LocalDateTimeUtils.toStrYearMonth(year, monthValue);
        LocalDateTime time = LocalDateTimeUtils.toLocalDateTime(yearMonth);
        //获取当前版本城市回款系数详情数据
        List<DmCityReturnCoefficient> cityList = returnCoefficientDetailMapper.queryCityDetail(cityId,time);
        if (CollectionUtils.isNotEmpty(cityList)) {
            List<ReturnCoefficientDetail> cityDetailList = new ArrayList<>();
            for (DmCityReturnCoefficient detail : cityList) {
                ReturnCoefficientDetail contrastContentDetil = new ReturnCoefficientDetail();
                String proProductCode = detail.getProProductCode();
                if (proProductCode.equals(BigStandardFormatsEnum.RESIDENCE.getKey()) || proProductCode.equals(BigStandardFormatsEnum.BUSINESS_VILLA_LIST.getKey()) || proProductCode.equals(BigStandardFormatsEnum.OTHER.getKey()) || proProductCode.equals(BigStandardFormatsEnum.PARKING.getKey())) {
                    continue;
                }
                contrastContentDetil.setProProductCode(proProductCode);
                contrastContentDetil.setOneMonth(detail.getOneMonth());
                contrastContentDetil.setTwoMonth(detail.getTwoMonth());
                contrastContentDetil.setThreeMonth(detail.getThreeMonth());
                contrastContentDetil.setFourMonth(detail.getFourMonth());
                contrastContentDetil.setFiveMonth(detail.getFiveMonth());
                contrastContentDetil.setSixMonth(detail.getSixMonth());
                contrastContentDetil.setSevenMonth(detail.getSevenMonth());
                contrastContentDetil.setEightMonth(detail.getEightMonth());
                contrastContentDetil.setNineMonth(detail.getNineMonth());
                contrastContentDetil.setTenMonth(detail.getTenMonth());
                contrastContentDetil.setElevenMonth(detail.getElevenMonth());
                contrastContentDetil.setTwelveMonth(detail.getTwelveMonth());
                contrastContentDetil.setThirteenMonth(detail.getThirteenMonth());
                contrastContentDetil.setFourteenMonth(detail.getFourteenMonth());
                contrastContentDetil.setFifteenMonth(detail.getFifteenMonth());
                contrastContentDetil.setSixteenMonth(detail.getSixteenMonth());
                contrastContentDetil.setSeventeenMonth(detail.getSeventeenMonth());
                contrastContentDetil.setEighteenMonth(detail.getEighteenMonth());
                contrastContentDetil.setNineteenMonth(detail.getNineteenMonth());
                contrastContentDetil.setTwentyMonth(detail.getTwentyMonth());
                contrastContentDetil.setTwentyOneMonth(detail.getTwentyOneMonth());
                contrastContentDetil.setTwentyTwoMonth(detail.getTwentyTwoMonth());
                contrastContentDetil.setTwentyThreeMonth(detail.getTwentyThreeMonth());
                contrastContentDetil.setTwentyFourMonth(detail.getTwentyFourMonth());
                cityDetailList.add(contrastContentDetil);

            }
            Map<String, Map<String, ContentDetil>> vsCityList = getVsVersionList(adjustmentDetailList, cityDetailList);
            content.setVsCityMap(vsCityList);
        }
        return content;
    }

    /**
     * 获取编辑版与其他版本对比集合
     *
     * @param adjustmentDetailList 编辑版详情列表
     * @param detailList           对比版本详情列表
     * @return List<Map < key:版本或差异 ， value ： < key:标准业态 ， value ： 详情>>>
     */
    private Map<String, Map<String, ContentDetil>> getVsVersionList(List<ReturnCoefficientDetail> adjustmentDetailList, List<ReturnCoefficientDetail> detailList) {
        ///List<Map<key:版本或差异，value：<key:标准业态，value：详情>>>
        Map<String, Map<String, ContentDetil>> vsInvestMap = new HashMap<>();


        //调整板新建adjustmentMap<key:标准业态，value：详情>
        Map<String, ContentDetil> adjustmentDetilMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(adjustmentDetailList)) {

            for (ReturnCoefficientDetail adjustmentDetail : adjustmentDetailList) {
                //调整板详情
                ContentDetil adjustmentContentDetil = new ContentDetil();
                //设置24月数据
                adjustmentContentDetil.setOneMonth(adjustmentDetail.getOneMonth());
                adjustmentContentDetil.setTwoMonth(adjustmentDetail.getTwoMonth());
                adjustmentContentDetil.setThreeMonth(adjustmentDetail.getThreeMonth());
                adjustmentContentDetil.setFourMonth(adjustmentDetail.getFourMonth());
                adjustmentContentDetil.setFiveMonth(adjustmentDetail.getFiveMonth());
                adjustmentContentDetil.setSixMonth(adjustmentDetail.getSixMonth());
                adjustmentContentDetil.setSevenMonth(adjustmentDetail.getSevenMonth());
                adjustmentContentDetil.setEightMonth(adjustmentDetail.getEightMonth());
                adjustmentContentDetil.setNineMonth(adjustmentDetail.getNineMonth());
                adjustmentContentDetil.setTenMonth(adjustmentDetail.getTenMonth());
                adjustmentContentDetil.setElevenMonth(adjustmentDetail.getElevenMonth());
                adjustmentContentDetil.setTwelveMonth(adjustmentDetail.getTwelveMonth());
                adjustmentContentDetil.setThirteenMonth(adjustmentDetail.getThirteenMonth());
                adjustmentContentDetil.setFourteenMonth(adjustmentDetail.getFourteenMonth());
                adjustmentContentDetil.setFifteenMonth(adjustmentDetail.getFifteenMonth());
                adjustmentContentDetil.setSixteenMonth(adjustmentDetail.getSixteenMonth());
                adjustmentContentDetil.setSeventeenMonth(adjustmentDetail.getSeventeenMonth());
                adjustmentContentDetil.setEighteenMonth(adjustmentDetail.getEighteenMonth());
                adjustmentContentDetil.setNineteenMonth(adjustmentDetail.getNineteenMonth());
                adjustmentContentDetil.setTwentyMonth(adjustmentDetail.getTwentyMonth());
                adjustmentContentDetil.setTwentyOneMonth(adjustmentDetail.getTwentyOneMonth());
                adjustmentContentDetil.setTwentyTwoMonth(adjustmentDetail.getTwentyTwoMonth());
                adjustmentContentDetil.setTwentyThreeMonth(adjustmentDetail.getTwentyThreeMonth());
                adjustmentContentDetil.setTwentyFourMonth(adjustmentDetail.getTwentyFourMonth());
                //<key：标准业态，value：详情>
                adjustmentDetilMap.put(adjustmentDetail.getProProductCode(), adjustmentContentDetil);

            }
            //<key:版本或差异，value：<key:标准业态，value：详情>>
            vsInvestMap.put(ReturnVersionTypeEnum.ADJUSTMENT.getKey(), adjustmentDetilMap);
        } else {
            throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_VERSION_ERROR);
        }

        //传入版本<key:标准业态，value：详情>
        Map<String, ContentDetil> contrastDetilMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(detailList)) {

            //传入版本详情数据
            for (ReturnCoefficientDetail detail : detailList) {
                //投资正式版详情
                ContentDetil contrastContentDetil = new ContentDetil();
                //设置24月数据
                contrastContentDetil.setOneMonth(detail.getOneMonth());
                contrastContentDetil.setTwoMonth(detail.getTwoMonth());
                contrastContentDetil.setThreeMonth(detail.getThreeMonth());
                contrastContentDetil.setFourMonth(detail.getFourMonth());
                contrastContentDetil.setFiveMonth(detail.getFiveMonth());
                contrastContentDetil.setSixMonth(detail.getSixMonth());
                contrastContentDetil.setSevenMonth(detail.getSevenMonth());
                contrastContentDetil.setEightMonth(detail.getEightMonth());
                contrastContentDetil.setNineMonth(detail.getNineMonth());
                contrastContentDetil.setTenMonth(detail.getTenMonth());
                contrastContentDetil.setElevenMonth(detail.getElevenMonth());
                contrastContentDetil.setTwelveMonth(detail.getTwelveMonth());
                contrastContentDetil.setThirteenMonth(detail.getThirteenMonth());
                contrastContentDetil.setFourteenMonth(detail.getFourteenMonth());
                contrastContentDetil.setFifteenMonth(detail.getFifteenMonth());
                contrastContentDetil.setSixteenMonth(detail.getSixteenMonth());
                contrastContentDetil.setSeventeenMonth(detail.getSeventeenMonth());
                contrastContentDetil.setEighteenMonth(detail.getEighteenMonth());
                contrastContentDetil.setNineteenMonth(detail.getNineteenMonth());
                contrastContentDetil.setTwentyMonth(detail.getTwentyMonth());
                contrastContentDetil.setTwentyOneMonth(detail.getTwentyOneMonth());
                contrastContentDetil.setTwentyTwoMonth(detail.getTwentyTwoMonth());
                contrastContentDetil.setTwentyThreeMonth(detail.getTwentyThreeMonth());
                contrastContentDetil.setTwentyFourMonth(detail.getTwentyFourMonth());
                contrastDetilMap.put(detail.getProProductCode(), contrastContentDetil);
            }

            vsInvestMap.put(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey(), contrastDetilMap);

        }


        return vsInvestMap;
    }


    /**
     * 审批校验
     * @param versionId 版本id
     */
    @Override
    public void check(String versionId) {
        //获取回款系数版本
        ProjectReturnCoefficient coefficient = projectReturnCoefficientWrapper.selectById(versionId, IsDeleteEnum.NO.getKey());
        //获取版本状态
        if (coefficient == null) {
            throw new MsgException(CodeEnum.NON_VERSIONS);
        }
        //调整版回款系数版本状态为【编制中】【待提交审批】【审批已驳回】时可以发起审批
        //调整版回款系数版本状态为【待编制】【审批通过】【审批中】或者没有调整版回款系数版本时不允许发起审批
        String versionState = coefficient.getVersionState();
        if (versionState.equals(VersionStatusEnum.ORGANIZATION.getKey()) || versionState.equals(VersionStatusEnum.EXAMINEDAPPROVED.getKey()) 
        		|| versionState.equals(VersionStatusEnum.FAILUREAPPROVED.getKey())) {
            return;
        } else {
            throw new MsgException(CodeEnum.PRO_PRODUCT_CODE_BY_PROJECT_VERSION_NOT_VERSION_APPROVED);
        }
    }

    /**
     * 修改审批状态
     *
     * @param versionId    版本id
     * @param versionState 审批状态
     */
    @Override
    public void updateState(String versionId, String versionState) {
        LocalDateTime now = LocalDateTime.now();
        //校验参数是否正确
        if (versionState.equals(VersionStatusEnum.NOTCREATE.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else if (versionState.equals(VersionStatusEnum.NOTPREPARED.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else if (versionState.equals(VersionStatusEnum.ORGANIZATION.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else if (versionState.equals(VersionStatusEnum.EXAMINEDAPPROVED.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else if (versionState.equals(VersionStatusEnum.FAILUREAPPROVED.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else if (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else if (versionState.equals(VersionStatusEnum.APPROVED.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else if (versionState.equals(VersionStatusEnum.SYSGENERATION.getKey())) {
            returnCoefficientMapper.updateStateByVersionId(versionId, versionState, now);
        } else {
            throw new MsgException(CodeEnum.SYS_OPER_ERROR);
        }


    }

    /**
     * 提交到OA审批
     *
     * @param returnCoefficientContentVo 参数
     * @param user                       用户
     * @return
     */
    @Override
    public String getSubmitToOA(ReturnCoefficientContentVo returnCoefficientContentVo, IdmUser user) {
        //项目id
        String projectId = returnCoefficientContentVo.getProjectId();
        //版本id
        String coefficientId = returnCoefficientContentVo.getVersionId();
        //审批单id
        String examineId = returnCoefficientContentVo.getExamineId();
        //参数校验
        if (StringUtils.isEmpty(projectId) && StringUtils.isEmpty(coefficientId) && StringUtils.isNotEmpty(examineId)) {
            ApprovalPreview approvalPreview = approvalPreviewMapper.selectByBillId(examineId, IsDeleteEnum.NO.getKey());
            if (null == approvalPreview) {
                throw new MsgException(CodeEnum.SYS_OPER_ERROR);
            }
            String contentString = approvalPreview.getContent();
            ReturnCoefficientContent content = JsonUtils.convertJsonToBean(contentString, ReturnCoefficientContent.class);

            if (null == content) {
                throw new MsgException(CodeEnum.SYS_OPER_ERROR);
            }
            content.setDescription(returnCoefficientContentVo.getDescription());
            List<FilePreviewVO> files = fileUploadService.getFilePreview(examineId);
            content.setFiles(files);
            projectId = content.getProjectId();
            coefficientId = content.getCoefficientId();

        }
        //查询是否存在未完成的审批单
        ApprovalBill approvalBill = new ApprovalBill();
        if (StringUtils.isBlank(examineId)) {
            approvalBill = approvalBillService.getNotSubmitApprovalBill(projectId, ProcessTypeEnum.MONEY_BACK_COEFFICIENT.getKey());
        } else {
            approvalBill = approvalBillService.getById(examineId);
            projectId = approvalBill.getProjectId();
        }
        //获取审批流程
        String flowKey = submitApprovedProjectService.getFlowKey(ProcessTypeEnum.MONEY_BACK_COEFFICIENT.getKey(), projectId);
        if (StringUtils.isBlank(flowKey)) {
            throw new MsgException(CodeEnum.FLOW_KEY_IS_NULL);
        }
        //已存在未完成的审批单 -> 更新审批内容，重新提交审批
        if (null != approvalBill) {
            ApprovalSubmitBO bo = new ApprovalSubmitBO();
            bo.setOaApprovalId(approvalBill.getId());
            bo.setAlias(user.getAlias());
            bo.setUsercn(user.getUsercn());
            bo.setFlowKey(flowKey);
            bo.setDescription(returnCoefficientContentVo.getDescription());
            bo.setSubject(approvalBill.getSubject());
            bo.setProcessType(approvalBill.getBusinessType());
            com.alibaba.fastjson.JSONObject vars = new com.alibaba.fastjson.JSONObject();
            vars.put("projectId", projectId);
            bo.setVars(vars);
            //将审批提交到OA
            approvalBill = approvalBillService.submit(bo);

            // 修改上传文件信息
            if (CollectionUtils.isNotEmpty(returnCoefficientContentVo.getFiles())) {
                fileUploadService.updateBillId(approvalBill.getId(), returnCoefficientContentVo.getFiles());
            }
            examineId = approvalBill.getId();
            // 查询上传附件
            List<FilePreviewVO> files = fileUploadService.getFilePreview(approvalBill.getId());
            String content = approvalPreviewService.getContentByApprovalId(examineId);
            ReturnCoefficientContent vo = JsonUtils.convertJsonToBean(content, ReturnCoefficientContent.class);
            if (null != vo) {
                String description = returnCoefficientContentVo.getDescription();
                vo.setDescription(description);
                vo.setFiles(files);
                //保存审批内容
                approvalPreviewService.saveData(approvalBill.getId(), JSON.toJSONString(vo), user);
            }
            //更新修改时间
            returnCoefficientMapper.updateCoefficientTime(coefficientId, LocalDateTime.now());

        } else {
            //不存在未完成的审批单 -> 发起新的审批单,保存审批内容
            //获取审批内容
            String contentString = this.getApprovalPreview(projectId, coefficientId, user, null);
            ReturnCoefficientContent content = JsonUtils.convertJsonToBean(contentString, ReturnCoefficientContent.class);
            if (null == content) {
                throw new MsgException(CodeEnum.SYS_OPER_ERROR);
            }
            String projectName = content.getProjectName();
            ApprovalSubmitBO bo = new ApprovalSubmitBO();
            bo.setAlias(user.getAlias());
            bo.setFlowKey(flowKey);
            bo.setSubject("【回款系数审批】" + projectName + "回款系数审批");
            bo.setDescription(content.getDescription());
            bo.setProjectId(projectId);
            bo.setProcessType(ProcessTypeEnum.MONEY_BACK_COEFFICIENT.getKey());

            com.alibaba.fastjson.JSONObject vars = new com.alibaba.fastjson.JSONObject();
            vars.put("projectId", projectId);
            bo.setVars(vars);
            ApprovalBillDetail approvalBillDetail = new ApprovalBillDetail();
            approvalBillDetail.setVersionId(coefficientId);
            ArrayList<ApprovalBillDetail> list = new ArrayList<>();
            list.add(approvalBillDetail);
            bo.setDetailList(list);
            //提交到OA审批
            approvalBill = approvalBillService.submit(bo);
            if (null != approvalBill) {
                if (CollectionUtils.isNotEmpty(returnCoefficientContentVo.getFiles())) {
                    fileUploadService.updateBillId(approvalBill.getId(), returnCoefficientContentVo.getFiles());
                }
                List<FilePreviewVO> files = fileUploadService.getFilePreview(approvalBill.getId());
                content.setFiles(files);
                content.setDescription(returnCoefficientContentVo.getDescription());

                contentString = JSONObject.toJSONString(content);
                //修改版本状态为待提交审批
                returnCoefficientMapper.updateCoefficientType(coefficientId, VersionStatusEnum.EXAMINEDAPPROVED.getKey(), LocalDateTime.now());
                //保存到回款系数审批快照
                approvalPreviewService.saveData(approvalBill.getId(), contentString, user);
            }
        }

        //返回审批预览Url
        return approvalBillService.getPreviewUrl(approvalBill);
    }

    /**
     * 修改审批状态
     * @param coefficientId 版本id
     * @param state         审批状态
     * @param now
     */
    @Override
    public void successServed(String coefficientId, String state, LocalDateTime now) {
        returnCoefficientMapper.updateStateByVersionId(coefficientId, state, now);

    }



    /**
     * 同步投资板回款系数
     * @return
     */
    @Override
    public void syncInvestmentCoefficient(String projectId) {
        //获取项目列表
        List<MdmProject> projectList = new ArrayList<>();
        if(StringUtils.isNotBlank(projectId)){
            MdmProject project = projectMapper.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
            projectList = Arrays.asList(project);
        }else {
            projectList = projectService.selectAll();
        }

        //循环项目列表，创建项目投资板回款系数
        for (MdmProject project : projectList) {
            //同步拉取投资系统 -> 投资回款系数
            Map<String, Map<Integer, BigDecimal>> codeCoefficientMap = syncInvestmentDetail(project.getProjectCode());
            if(CollectionUtils.isNotEmpty(codeCoefficientMap)){
                createInvestmentCoefficient(project,codeCoefficientMap);
            }
        }
    }

    /**
     * 创建投资板回款系数
     * @param projectId 项目id
     * @param codeCoefficientMap
     * @return
     */
    private synchronized void createInvestmentCoefficient(MdmProject project, Map<String, Map<Integer, BigDecimal>> codeCoefficientMap) {
        //获取最新投资正式版
        ProjectReturnCoefficient returnCoefficient = projectReturnCoefficientWrapper.selectNewestByProjectId(project.getProjectId(), ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey(), IsDeleteEnum.NO.getKey());
        //查询全盘签约计划版本列表
        List<String> signIdList = signPlanVersionService.getOverallSignVersionList(project.getProjectId());
        //不存在签约计划版本
        if (CollectionUtils.isEmpty(signIdList)) {
            return;
        }
        //获取标准业态下全部子类code集合
        HashMap<String, List<String>> standardCodeMap = getStandardCodeMap(signIdList);

        //现有投资正式版为空新建版本
        if (null == returnCoefficient) {
            //新建版本
            returnCoefficient = creatInvestmentVersion(project, returnCoefficient);
            creatInvestmentDetail(codeCoefficientMap, standardCodeMap, returnCoefficient);
        }else {
            //获取回款系数详情列表
            List<ReturnCoefficientDetail> coefficientDetailList = returnCoefficientDetailWrapper.selectByCoefficientId(returnCoefficient.getId(), IsDeleteEnum.NO.getKey());
            //转成业态系数Map
            Map<String, Map<Integer, BigDecimal>> oldCodeCoefficientMap = coefficientDetailList.stream().collect(Collectors.toMap(ReturnCoefficientDetail::getProProductCode, ReturnCoefficientDetail::getCoefficientTwoMap));
            //判断是否和现有数据相同 相同则只更改同步时间和更新时间  不相同则新增版本
            boolean compareResult = compareCodeCoefficientMap(codeCoefficientMap,oldCodeCoefficientMap);
            if(compareResult){
                //更新同步时间和修改时间
                returnCoefficientMapper.updateTimeById(returnCoefficient.getId(), LocalDateTime.now());
            }else {
                //新建版本
                returnCoefficient = creatInvestmentVersion(project, returnCoefficient);
                creatInvestmentDetail(codeCoefficientMap, standardCodeMap, returnCoefficient);
            }
        }
    }

    /**
     *  新建回款系数详情表
     * @param codeCoefficientMap
     * @param project
     * @param returnCoefficient
     */
    private void creatInvestmentDetail(Map<String, Map<Integer, BigDecimal>> codeCoefficientMap, HashMap<String, List<String>> standardCodeMap, ProjectReturnCoefficient returnCoefficient) {
        //key:项目下全部标准业态
        Set<String> codeList = standardCodeMap.keySet();
        for (String code : codeList) {
            ReturnCoefficientDetail detail = new ReturnCoefficientDetail();
            //回款系数详情表id
            detail.setId(UUIDUtils.create());
            //回款系数版本表id
            detail.setCoefficientId(returnCoefficient.getId());
            //创建人员
            detail.setCreateBy(Constants.SYS);
            //创建日期
            detail.setCreateTime(LocalDateTime.now());
            //是否删除
            detail.setIsDelete(IsDeleteEnum.NO.getKey());
            //标准业态编码
            detail.setProProductCode(code);
            //标准业态type
            detail.setProProductType(StandardFormatsEnum.getValueByKey(code));
            //大业态编码
            detail.setThreeProductCode(StandardFormatsMapEnum.getValueByKey(code));
            //大业态名称
            detail.setThreeProductName(StandardFormatsEnum.getValueByKey(code));

            Map<Integer, BigDecimal> coefficientMap = codeCoefficientMap.get(code);
            if (MapUtils.isNotEmpty(coefficientMap)) {
                detail.setOneMonth(coefficientMap.get(1));
                detail.setTwoMonth(coefficientMap.get(2));
                detail.setThreeMonth(coefficientMap.get(3));
                detail.setFourMonth(coefficientMap.get(4));
                detail.setFiveMonth(coefficientMap.get(5));
                detail.setSixMonth(coefficientMap.get(6));
                detail.setSevenMonth(coefficientMap.get(7));
                detail.setEightMonth(coefficientMap.get(8));
                detail.setNineMonth(coefficientMap.get(9));
                detail.setTenMonth(coefficientMap.get(10));
                detail.setElevenMonth(coefficientMap.get(11));
                detail.setTwelveMonth(coefficientMap.get(12));
                detail.setThirteenMonth(BigDecimal.ZERO);
                detail.setFourteenMonth(BigDecimal.ZERO);
                detail.setFifteenMonth(BigDecimal.ZERO);
                detail.setSixteenMonth(BigDecimal.ZERO);
                detail.setSeventeenMonth(BigDecimal.ZERO);
                detail.setEighteenMonth(BigDecimal.ZERO);
                detail.setNineteenMonth(BigDecimal.ZERO);
                detail.setTwentyMonth(BigDecimal.ZERO);
                detail.setTwentyOneMonth(BigDecimal.ZERO);
                detail.setTwentyTwoMonth(BigDecimal.ZERO);
                detail.setTwentyThreeMonth(BigDecimal.ZERO);
                detail.setTwentyFourMonth(BigDecimal.ZERO);
                returnCoefficientDetailMapper.insert(detail);
            }
        }
    }

    /**
     * 同步投资回款系数
     * @param projectCode
     * @return
     */
    private Map<String, Map<Integer, BigDecimal>> syncInvestmentDetail(String projectCode) {
        BasicAuthClient bac = new BasicAuthClient();
        String time = LocalDateTimeUtils.formatTime(LocalDateTime.now(), DateUtils.DATE_FULL_STR);
        //请求数据封装
        InvestmentCoefficientJson investmentCoefficientJson = new InvestmentCoefficientJson();
        investmentCoefficientJson.getEsbInfo().setInstId("instId001");
        investmentCoefficientJson.getEsbInfo().setRequestTime(time);
        investmentCoefficientJson.getEsbInfo().setInstId("instId001");
        investmentCoefficientJson.getEsbInfo().setRequestTime(time);
        investmentCoefficientJson.getRequestInfo().getProject().setBeginTime("2000-01-01 00:00:00");
        investmentCoefficientJson.getRequestInfo().getProject().setEndTime(time);
        investmentCoefficientJson.getRequestInfo().getProject().setLandPids(Arrays.asList(projectCode));

        String jsonParam = JSONSerializer.toJSON(investmentCoefficientJson).toString();
        log.info("#######同步投资正式版回款系数 参数："+ jsonParam);
        String result = bac.post(investment_push_url, jsonParam, api_name, api_key);
        log.info("#######同步投资正式版回款系数 数据："+ result);
        if(StringUtils.isEmpty(result)) {
            return null;
        }
        if(null == JSONObject.parseObject(result).getJSONObject("resultInfo")
                || null == JSONObject.parseObject(result).getJSONObject("resultInfo").getJSONObject("body")){
            return null;
        }
        JSONArray jsonArray = JSONObject.parseObject(result).getJSONObject("resultInfo").getJSONObject("body").getJSONArray("content");
        if (CollectionUtils.isEmpty(jsonArray)) {
            return null;
        }

        //转成系数列表
        List<InvestmentOfficialVersion> investmentList = com.alibaba.fastjson.JSONObject.parseArray(jsonArray.toJSONString(), InvestmentOfficialVersion.class);
        //转成业态系数Map
        Map<String, Map<Integer, BigDecimal>> codeCoefficientMap = getCoefficientMap(investmentList);
        return codeCoefficientMap;
    }


    /**
     * 根据组织机构类型 返回上级类型
     *
     * @param hrOrgTypeId
     */
    public String getOrgNextType(String hrOrgTypeId) {
        if (hrOrgTypeId.equals(HrOrgTypeEunm.ORG_11.getKey())) {
            return HrOrgTypeEunm.ORG_20.getKey();
        }
        if (hrOrgTypeId.equals(HrOrgTypeEunm.ORG_20.getKey())) {
            return HrOrgTypeEunm.ORG_21.getKey();
        }
        if (hrOrgTypeId.equals(HrOrgTypeEunm.ORG_21.getKey())) {
            return HrOrgTypeEunm.ORG_31.getKey();
        }

        return "";
    }

    /**
     * 比较业态系数Map
     * @param codeCoefficientMap
     * @param oldCodeCoefficientMap
     * @return
     */
    private boolean compareCodeCoefficientMap(Map<String, Map<Integer, BigDecimal>> codeCoefficientMap, Map<String, Map<Integer, BigDecimal>> oldCodeCoefficientMap) {
        for (Map.Entry<String, Map<Integer, BigDecimal>> oldCodeCoefficientMapEntry : oldCodeCoefficientMap.entrySet()){
            if(codeCoefficientMap.containsKey(oldCodeCoefficientMapEntry.getKey())){
                Map<Integer, BigDecimal> oldCoefficientMap = oldCodeCoefficientMapEntry.getValue();
                Map<Integer, BigDecimal> coefficientMap = codeCoefficientMap.get(oldCodeCoefficientMapEntry.getKey());

                for (Map.Entry<Integer, BigDecimal> oldCoefficientMapEntry : oldCoefficientMap.entrySet()){
                    if(oldCoefficientMapEntry.getKey() > 12){
                        continue;
                    }
                    if(coefficientMap.containsKey(oldCoefficientMapEntry.getKey())){
                        BigDecimal oldCoefficient = oldCoefficientMapEntry.getValue();
                        BigDecimal coefficient = coefficientMap.get(oldCoefficientMapEntry.getKey());
                        if(coefficient.compareTo(oldCoefficient) != 0){
                            return false;
                        }
                    }else {
                        return false;
                    }
                }
            }else {
                return false;
            }
        }
        return true;
    }

    /**
     * 转成业态系数Map
     * @param investmentList
     * @return
     */
    private Map<String, Map<Integer, BigDecimal>> getCoefficientMap(List<InvestmentOfficialVersion> investmentList) {
        Map<String, Map<Integer, BigDecimal>> coefficientMap = new HashMap<>();
        Map<Integer, BigDecimal> businessMap = investmentList.stream().collect(Collectors.toMap(InvestmentOfficialVersion::getSortNo, s-> s.getBusiness().setScale(5, RoundingMode.HALF_UP)));
        Map<Integer, BigDecimal> houseMap = investmentList.stream().collect(Collectors.toMap(InvestmentOfficialVersion::getSortNo, s->s.getHouse().setScale(5, RoundingMode.HALF_UP)));
        Map<Integer, BigDecimal> parkingMap = investmentList.stream().collect(Collectors.toMap(InvestmentOfficialVersion::getSortNo, s->s.getParkingSpace().setScale(5, RoundingMode.HALF_UP)));

        List<String> businessCodeList = StandardFormatsMapEnum.getKeyByValue(BigStandardFormatsEnum.BUSINESS_VILLA_LIST.getKey());
        for(String code : businessCodeList){
            coefficientMap.put(code,businessMap);
        }
        List<String> houseCodeList = StandardFormatsMapEnum.getKeyByValue(BigStandardFormatsEnum.RESIDENCE.getKey());
        for(String code : houseCodeList){
            coefficientMap.put(code,houseMap);
        }
        List<String> parkingCodeList = StandardFormatsMapEnum.getKeyByValue(BigStandardFormatsEnum.PARKING.getKey());
        for(String code : parkingCodeList){
            coefficientMap.put(code,parkingMap);
        }
        return coefficientMap;
    }

    private boolean judgeSame(Map<Integer, BigDecimal> oldMap, Map<Integer, BigDecimal> newMap) {
        Set<Integer> integers = oldMap.keySet();
        for (Integer integer : integers) {
            BigDecimal oldCoefficient = oldMap.get(integer);
            BigDecimal newCoefficient = newMap.get(integer);
            if (oldCoefficient.compareTo(newCoefficient) != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * 新建投资正式版
     *
     * @param businessMap 商业
     * @param houseMap    住宅
     * @param stallMap    车位
     * @param projectId   项目id
     */
    private ProjectReturnCoefficient creatInvestmentVersion(MdmProject project, ProjectReturnCoefficient returnCoefficient) {
        //创建回款系数版本和详情
        ProjectReturnCoefficient coefficient = new ProjectReturnCoefficient();

        //版本
        String versionNum = null;
        //如果为空新建版本
        if (null == returnCoefficient) {
            versionNum = "V1";
        } else {
            versionNum = VersionUtils.bigVersionInc(returnCoefficient.getVersionNum());
        }

        String versionId = UUIDUtils.create();
        coefficient.setId(versionId);
        coefficient.setProjectId(project.getProjectId());
        coefficient.setCityId(project.getCompanyId());
        coefficient.setVersionType(ReturnVersionTypeEnum.INVEST_OFFICIAL.getKey());
        coefficient.setVersionNum(versionNum);
        coefficient.setVersionState(VersionStatusEnum.SYSGENERATION.getKey());
        coefficient.setSyncTime(LocalDateTime.now());
        coefficient.setAffiliationMonth(LocalDateTimeUtils.formatTime(LocalDateTime.now(),DateUtils.DATE_JFP_STR));
        coefficient.setCreateBy(Constants.SYS);
        coefficient.setCreateTime(LocalDateTime.now());
        coefficient.setVersionCreate(VersionCreateEnum.AUTOMATICCREATE.getKey());
        coefficient.setIsDelete(IsDeleteEnum.NO.getKey());
        this.save(coefficient);

        return coefficient;
    }


    /**
     * 获取区域财务PM人员
     *
     * @param projectId 项目id
     * @return
     */
    private List<String> getFinancePm(String projectId) {

        List<String> userList = Collections.synchronizedList(new ArrayList<>());
        //根据项目id获取城市公司信息中的区域ID
        String areaId = returnCoefficientMapper.getCityCompany(projectId);

        //根据城市公司信息中的区域ID获取区域财务PM人员
        HashSet<GroupUserVo> set = idmUserService.getGroupUserInfo(Constants.PROJECT_FINANCE_PM, areaId);
        if (CollectionUtils.isNotEmpty(set)) {
            for (GroupUserVo vo : set) {
                userList.add(vo.getUsername());
            }
        }
        return userList;
    }

    /**
     * 查询权益比例
     *
     * @param projectId
     * @return
     */
    public String getEquityRatioRate(String projectId) {
        BigDecimal equityRatio = BigDecimal.ZERO;
        MdmProjectPatner projectPartner = projectBasicService.selecteQuityRatio(projectId);
        if (projectPartner != null) {
            if (projectPartner.getEquityRatio() != null) {
                equityRatio = projectPartner.getEquityRatio();
            }
        }
        return equityRatio.toString();
    }


    /**
     * 新建实际版回款系数版本
     *
     * @param projectId 项目id
     * @return
     */

    public ProjectReturnCoefficient createRealityForNos(String projectId) {
        //查询分期数据
        ProjectByStagesDto project = projectByStagesMapper.selectByOrgdepid(projectId);
        if (null == project) {
            throw new MsgException(CodeEnum.SYS_PROJECT_ERROR);
        }
        //获取全部实际版版本
        List<ProjectReturnCoefficient> coefficientList = returnCoefficientMapper.selectVersions(projectId, IsDeleteEnum.NO.getKey(), ReturnVersionTypeEnum.PRACTICAL.getKey());
        //根据项目id获取城市id
        String cityId = returnCoefficientDetailMapper.selectCityOfProject(projectId);  //获取最新实际版版本状态

        ProjectReturnCoefficient coefficient = projectReturnCoefficientWrapper.selectNewestByProjectId(projectId, ReturnVersionTypeEnum.PRACTICAL.getKey(), IsDeleteEnum.NO.getKey());
        String versionNum = null;
        //如果实际版为空新建版本
        if (CollectionUtils.isEmpty(coefficientList)) {
            versionNum = "V1";
        } else {
            LocalDateTime createTime = coefficient.getCreateTime();
            Month month = createTime.getMonth();
            if (month.equals(LocalDateTime.now().getMonth())){

                versionNum = coefficient.getVersionNum();
                if (StringUtils.isEmpty(versionNum)) {
                    versionNum = "V1";
                } else {
                    String s = versionNum.substring(1);
                    int i = Integer.parseInt(s);
                    versionNum = "V" + (++i);
                }
            }else {
                versionNum = "V1";
            }

        }
        ProjectReturnCoefficient projectReturnCoefficient = new ProjectReturnCoefficient();
        String coefficientId = UUIDUtils.create();//新建回款系数版本表id
        //判断coefficient是否为空
        if (null == coefficient) {
            projectReturnCoefficient.setId(coefficientId);//新增回款系数版本id
            projectReturnCoefficient.setProjectId(projectId);//新增项目id
            projectReturnCoefficient.setCityId(cityId);//城市id
            projectReturnCoefficient.setDataSource(FetchNnumberEnum.NOS.getKey());//设置为nos系统
            projectReturnCoefficient.setSyncTime(LocalDateTime.now());//同步时间为现在
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM");
            projectReturnCoefficient.setAffiliationMonth(df.format(LocalDateTime.now()));//版本归属时间
            projectReturnCoefficient.setVersionType(ReturnVersionTypeEnum.PRACTICAL.getKey());//版本类型为实际版
            projectReturnCoefficient.setVersionState(VersionStatusEnum.SYSGENERATION.getKey());//版本状态系统生成
            projectReturnCoefficient.setVersionNum(versionNum);//版本号
            projectReturnCoefficient.setCreateBy(Constants.SYS);//创建人员
            projectReturnCoefficient.setCreateTime(LocalDateTime.now());//创建时间
            projectReturnCoefficient.setCreateTime(LocalDateTime.now());//修改时间
            projectReturnCoefficient.setIsDelete(0);//是否删除
            projectReturnCoefficient.setDescription("0");//备注信息
            projectReturnCoefficient.setVersionCreate(VersionCreateEnum.MANUALCREATE.getKey());
            //保存新建回款系数版本信息
            this.save(projectReturnCoefficient);

        } else {
            //创建调整板回款系数
            projectReturnCoefficient.setId(coefficientId);//新增回款系数版本id
            projectReturnCoefficient.setProjectId(projectId);//新增项目id
            projectReturnCoefficient.setCityId(coefficient.getCityId());
            projectReturnCoefficient.setDataSource(coefficient.getDataSource());
            projectReturnCoefficient.setSyncTime(LocalDateTime.now());
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM");
            projectReturnCoefficient.setAffiliationMonth(df.format(LocalDateTime.now()));
            projectReturnCoefficient.setVersionType(ReturnVersionTypeEnum.PRACTICAL.getKey());//版本类型为实际版
            projectReturnCoefficient.setVersionState(VersionStatusEnum.SYSGENERATION.getKey());//版本状态为系统生成
            projectReturnCoefficient.setVersionNum(versionNum);//版本号为v1
            projectReturnCoefficient.setCreateBy(Constants.SYS);//创建人员
            projectReturnCoefficient.setCreateTime(LocalDateTime.now());//创建时间
            projectReturnCoefficient.setIsDelete(0);
            projectReturnCoefficient.setDescription(coefficient.getDescription());
            projectReturnCoefficient.setVersionCreate(VersionCreateEnum.MANUALCREATE.getKey());
            //保存新建回款系数版本信息
            this.save(projectReturnCoefficient);

        }


        return projectReturnCoefficient;
    }

    /**
     * 添加日志
     *
     * @param title
     * @param content
     */
    private void saveLog(String module,String title,String url,String content,String isSuccess) {
        SysLogBO bo = new SysLogBO();
        bo.setEvent(LogEventEnum.TIMERTASK);
        bo.setSource(LogSrcEnum.SYS);
        String hostAddr = WebUtils.getLocalIP();
        bo.setIp(hostAddr);
        bo.setModule(module);
        bo.setTitle(title);
        bo.setContent(content);
        bo.setUrl(url);
        bo.setType(LogTypeEnum.ONE.getKey());
        bo.setIsSuccess(IsSuccessEnum.SUCCESS.getKey());
        sysLogService.add(bo, Constants.SYS);
    }

    /**
     * 获取标准业态下全部子类code集合
     */
    private HashMap<String, List<String>> getStandardCodeMap(List<String> signIdList) {
        List<PanoplanBuildPlanItem> buildPlanList = returnCoefficientDetailWrapper.queryBySingIdList(signIdList);

        //map(key:标准业态编码,value：子类编码集合)
        HashMap<String, List<String>> map = new HashMap<>();

        HashSet<String> set = new HashSet<>();
        for (PanoplanBuildPlanItem panoplanBuildPlanItem : buildPlanList) {
            String saleNum = panoplanBuildPlanItem.getSaleNum();
            if (SalyTypeEnum.NOT_RENTABLE.getKey().equals(saleNum) || SalyTypeEnum.RENTED.getKey().equals(saleNum)) {
                continue;
            }
            String productTypeNum = panoplanBuildPlanItem.getProductTypeNum();
            set.add(productTypeNum);
        }
        //获取所有标准业态下子类编码集合
        List<DictionaryCodeBO> dictionaryCodeList = sysDictionaryService.selectByCodes(new ArrayList<>(set));

        for (DictionaryCodeBO dictionaryCodeBO : dictionaryCodeList) {
            String parentCode = dictionaryCodeBO.getParentCode();
            map.put(parentCode, null);
        }
        for (DictionaryCodeBO dictionaryCodeBO : dictionaryCodeList) {
            String parentCode = dictionaryCodeBO.getParentCode();
            String childCode = dictionaryCodeBO.getChildCode();
            ArrayList<String> list = new ArrayList<>();
            Set<String> codes = map.keySet();
            for (String code : codes) {

                if (code.equals(parentCode)) {
                    list.add(childCode);
                }
            }
            map.put(parentCode, list);
        }
        return map;
    }


}





